<?php

namespace App\Console\Commands;

use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class ModelCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:model {table}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Execute the console command.
     * @throws Exception;
     */
    public function handle(): void
    {
        if (prod()) return;
        $table = $this->argument('table');
        $this->item(humpToLine(lcfirst($table)));
    }

    /**
     * item
     * @param string $table
     */
    private function item(string $table): void
    {
        $file = base_path('database/migrations/sql/' . $table . '.sql');
        if (!is_file($file)) return;
        $select = DB::select("show tables like '" . humpToLine($table) . "'");
        if (empty($select)) return;
        $list = DB::select('show full columns from `' . humpToLine($table) . '`');
        $table = lineToHump($table);
        $file = app_path('Models/' . ucfirst($table) . 'Model.php');
        $str = file_get_contents(base_path('database/model_class.txt'));
        $array = array_column($this->columns($table), 'column');
        $str = $this->castsHandle($list, $str);
        $str = $this->useHandle($list, $str, $table);
        $str = $this->hPrimaryKey($array, $str);
        $fieldStr = '';
        for ($i = 0; $i < count($array); $i++) {
            if ($i) $fieldStr .= '        ';
            $fieldStr .= "'$array[$i]'";
            if ($i !== count($array) - 1) $fieldStr .= ',' . PHP_EOL;
        }

        file_put_contents($file, strtr($str, [
            'ClassName' => ucfirst($table),
            'table_name' => humpToLine($table),
            '$fillableArr' => "$fieldStr",
        ]));
        $file = app_path('Library/Logic/' . ucfirst($table) . 'Logic.php');
        if (is_file($file)) return;
        $str = file_get_contents(base_path('database/logic_class.txt'));
        file_put_contents($file, strtr($str, ['ClassName' => ucfirst($table)]));
    }

    private function hPrimaryKey(array $array, string $str): string
    {
        if ($array[0] === 'id') {
            $str = strtr($str, [
                '
    primaryKey' => '',
            ]);
        } else {
            $str = strtr($str, [
                'primaryKey' => PHP_EOL . '    protected $primaryKey = ' . "'" . $array[0] . "';",
            ]);
        }
        return $str;
    }

    /**
     * Execute the console command.
     * @param array $array
     * @param string $str
     * @param string $table
     * @return string
     */
    private function useHandle(array $array, string $str, string $table): string
    {
        $array = array_column($array, 'Field');
        $use = '';
        $flag = 0;
        if (!in_array('deleted_at', $array)) {
            $str = strtr($str, [
                'useSoftDeletes;' . PHP_EOL => '',
            ]);
        } else {
            $str = strtr($str, [
                'useSoftDeletes;' => 'use Illuminate\Database\Eloquent\SoftDeletes;' . PHP_EOL,
            ]);
            $flag = 1;
            $use = 'SoftDeletes,';
        }
        $ormFile = app_path('Library/Traits/Orm/' . ucfirst($table) . 'OrmTrait.php');
        if (!is_file($ormFile)) {
            $str = strtr($str, [
                'useOrmTrait;' . PHP_EOL => '',
            ]);
        } else {
            $flagStr = $flag === 0 ? PHP_EOL : '';
            $str = strtr($str, [
                'useOrmTrait;' => 'use App\Library\Traits\Orm\\' . ucfirst($table) . 'OrmTrait;' . $flagStr,
            ]);
            if (strlen($use)) $use .= ' ';
            $use .= ucfirst($table) . 'OrmTrait,';
        }
        if (strlen($use) === 0) {
            $str = strtr($str, [
                '{use}' => '',
            ]);
            $str = strtr($str, [
                '{

    ' => '{' . PHP_EOL . '    ',
                'use App\Library\Models\Entity;' => 'use App\Library\Models\Entity;' . PHP_EOL,
            ]);
        } else {
            if (str_ends_with($use, ',')) {
                $use = substr($use, 0, -1) . ';';
            }
            $str = strtr($str, [
                '{use}' => 'use ' . $use . PHP_EOL . PHP_EOL,
                'protected $table = ' => '    protected $table = ',
            ]);
        }
        return $str;
    }

    /**
     * Execute the console command.
     * @param array $array
     * @param string $str
     * @return string
     */
    private function castsHandle(array $array, string $str): string
    {
        $flag = 0;
        $replace = '';
        foreach ($array as $value) {
            if ($value->Type === 'json') {
                $replace .= $flag ? ', ' : '';
                $flag++;
                $replace .= "'$value->Field' => 'json'";
            }
        }
        if (strlen($replace)) {
            $str = strtr($str, ['{casts}' => PHP_EOL . "    protected " . '$casts' . " = [$replace];" . PHP_EOL]);
        } else {
            $str = strtr($str, ['{casts}' => '']);
        }
        return $str;
    }

    /**
     * Execute the console command.
     * @param string $table
     * @return array
     */
    private function columns(string $table): array
    {
        $table = strtolower(humpToLine(lcfirst($table)));
        $file = base_path('database/migrations/sql/' . $table . '.sql');
        $handle = file($file);
        $array = [];
        for ($i = 3; $i < count($handle); $i++) {
            $str = trim(strtr($handle[$i], ['abc' => '']));
            $arr = array_merge(array_filter(array_unique(explode(' ', $str))));
            if (strtolower($arr[0]) == 'primary') break;
            $array[] = $arr;
        }
        foreach ($array as $k => $v) {
            $array[$k][0] = strtr($v[0], ['`' => '']);
            $array[$k]['column'] = $array[$k][0];
        }
        return $array;
    }
}

